#
# This file is a part of the open-eBackup project.
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
# If a copy of the MPL was not distributed with this file, You can obtain one at
# http://mozilla.org/MPL/2.0/.
#
# Copyright (c) [2024] Huawei Technologies Co.,Ltd.
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
#

import os
import sys

from gaussdbt.commons.const import ClusterStatus, ErrorCode, JSON_SCHEMA_PATH
from gaussdbt.resource.gaussdbt_resource import GaussCluster
from common.common import exter_attack
from common.const import ParamConstant, JobData, SysData, ExecuteResultEnum
from common.logger import Logger
from common.parse_parafile import ParamFileUtil
from common.util.check_utils import is_valid_id
from common.util.exec_utils import exec_overwrite_file

log = Logger().get_logger("gaussdbt_plugin.log")


class Resource:
    func_type = ""
    user_name = ""
    gauss_instance = GaussCluster()
    all_output = {
        'id': '', 'name': '', 'type': 'DataBase', 'subType': 'GaussDBT', 'endpoint': '',
        'nodes': [], 'extendInfo': ''
    }
    check_output = {'code': 200, 'bodyErr': 0, 'message': ''}

    @staticmethod
    def check_path_ok():
        """
        check path exist or not
        """
        log.info("Check path exist or not")
        if os.path.exists(ParamConstant.RESULT_PATH):
            return True
        else:
            log.error("The result file path does not exist!")
            return False

    def get_linux_input(self, input_func):
        """
        get input from system command line
        """
        log.info("Get input from system command line")
        self.func_type = input_func

    @exter_attack
    def check_user_right(self):
        """
        check the user name(authKey) is the same as database user name
        """
        GaussCluster.get_info_lines()
        cluster_state = GaussCluster.get_cluster_state()
        if cluster_state in ClusterStatus:
            self.check_output['code'] = 0
            self.check_output['message'] = f"Cluster State is {cluster_state}"
        else:
            self.check_output['bodyErr'] = ErrorCode.ERROR_USER_NOT_EXIST_CLUSTER
            self.check_output['message'] = "User name is wrong or Cluster dose not exist"
        result_file_name = "{}{}".format("result", JobData.PID)
        result_file_path = os.path.join(ParamConstant.RESULT_PATH, result_file_name)
        exec_overwrite_file(result_file_path, self.check_output)
        return self.check_output

    @exter_attack
    def get_cluster_info(self):
        """
        get all cluster information
        """
        log.info("Get all cluster information")
        GaussCluster.get_info_lines()
        hostname = self.gauss_instance.get_hostname()
        self.all_output['name'] = hostname
        all_nodes = self.gauss_instance.get_all_node()
        self.all_output['endpoint'] = self.gauss_instance.get_endpoint_by_hostname()
        self.all_output['extendInfo'] = {
            "clusterState": self.gauss_instance.get_cluster_state(),
            "runningState": self.gauss_instance.get_running_state(),
            "clusterVersion": self.gauss_instance.get_gdb_version(),
            "deployType": self.gauss_instance.get_deploy_type()
        }
        for this_node in all_nodes:
            node_status = {
                'status': this_node.status,
                'role': this_node.node_role
            }
            node = {
                'endpoint': this_node.node_ip,
                'extendInfo': node_status,
                'name': this_node.node_name,
                'subType': 'GaussDBT',
                'type': 'DataBase',
                'id': ''
            }
            try:
                self.all_output['nodes'].append(node)
            except KeyError:
                log.error("Dict key not exist!")
                return False
        return True


def do_main():
    new_instance = Resource()
    if new_instance.check_path_ok():
        new_instance.get_linux_input(sys.argv[1])
        JobData.PID = sys.argv[2]
        # 校验pid
        if not is_valid_id(JobData.PID):
            log.warn(f'pid is invalid!')
            sys.exit(1)
        try:
            ParamFileUtil.parse_param_file_and_valid_by_schema(JobData.PID, JSON_SCHEMA_PATH)
        except Exception as err:
            log.error(f"Failed to parse job param file for {err}")
            return ExecuteResultEnum.INTERNAL_ERROR
        if new_instance.func_type == "CheckApplication":
            new_instance.check_user_right()
        elif new_instance.func_type == "QueryCluster":
            new_instance.get_cluster_info()
            file_name = "{}{}".format("result", JobData.PID)
            result_file = os.path.join(ParamConstant.RESULT_PATH, file_name)
            exec_overwrite_file(result_file, new_instance.all_output)
        else:
            log.error("Wrong input from command line!")
        return ExecuteResultEnum.SUCCESS
    return ExecuteResultEnum.INTERNAL_ERROR


if __name__ == '__main__':
    log.info("Running main...")
    SysData.SYS_STDIN = sys.stdin.readline()
    sys.exit(do_main())
